package sample.qiplat.plugin.flog;

import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;

import com.qiplat.open.ui.util.DensityUtils;
import com.rapid.api.component.widget.log.LogGroupView;
import com.rapid.api.component.widget.log.LogView;
import com.rapid.api.ext.plugin.AndroidPlugins;
import com.rapid.api.logging.Diagnostic;
import com.rapid.api.logging.LogCategory;
import com.rapid.api.logging.LogMessage;
import com.rapid.util.android.ContextUtils;

/**
 * 悬浮Manager
 */
public class FloatWindowManager implements LogGroupView {
    private volatile static FloatWindowManager INSTANCE;
    private WindowManager windowManager;
    private Context context;
    private WindowManager.LayoutParams iconParams;
    private WindowManager.LayoutParams logParams;
    private int layoutY;
    private int layoutX;
    private ValueAnimator animator;
    private FloatLogView logView;
    private ImageView iconView;

    public static synchronized FloatWindowManager getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new FloatWindowManager();
        }
        return INSTANCE;
    }

    public FloatWindowManager initManager(Context context) {
        this.context = context;
        windowManager = (WindowManager) this.context.getSystemService(Context.WINDOW_SERVICE);
        initIconView();
        initLogView();
        return this;
    }

    public void showFloatWindow() {
        windowManager.addView(iconView, iconParams);
        windowManager.addView(logView, logParams);
    }

    private void initLogView() {
        logView = new FloatLogView(context);
        logView.setVisibility(View.GONE);
        logView.setOnHideClickListener(() -> {
            iconView.setVisibility(View.VISIBLE);
            logView.setVisibility(View.GONE);
        });
        logParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            logParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            logParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        }
        logParams.format = PixelFormat.RGBA_8888; //窗口透明
        logParams.gravity = Gravity.LEFT | Gravity.TOP; //窗口位置
        logParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        logParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        logParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        logParams.x = displayMetrics.widthPixels - iconView.getMeasuredWidth();
        logParams.y = dp2px(context, 150);
    }

    private void initIconView() {
        iconView = new ImageView(context);
        iconView.setImageDrawable(ContextUtils.getDrawable(
                AndroidPlugins.getContext(this),
                R.drawable.ic_log_icon
        ));
        iconParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            iconParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            iconParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        }
        iconParams.format = PixelFormat.RGBA_8888; //窗口透明
        iconParams.gravity = Gravity.LEFT | Gravity.TOP; //窗口位置
        iconParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        layoutY = dp2px(context, 150);
        layoutX = displayMetrics.widthPixels - iconView.getMeasuredWidth();
        iconParams.width = dp2px(context, 36);
        iconParams.height = dp2px(context, 45);
        iconParams.x = layoutX;
        iconParams.y = layoutY;
        setListener();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void setListener() {
        iconView.setOnClickListener(v -> {
            logView.setVisibility(View.VISIBLE);
            iconView.setVisibility(View.GONE);
        });
        iconView.setOnTouchListener(new View.OnTouchListener() {
            private int moveX;     //动画平移距离
            int startX, startY;    //起始点
            boolean isMove;    //是否在移动
            long startTime;
            int finalMoveX;    //最后通过动画将mView的X轴坐标移动到finalMoveX
            boolean downMove = false;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        startX = (int) event.getX();
                        startY = (int) event.getY();
                        startTime = System.currentTimeMillis();
                        isMove = false;
                        downMove = false;
                        return false;
                    case MotionEvent.ACTION_MOVE:
                        if (Math.abs(startX - event.getX()) > 2 || Math.abs(startY - event.getY()) > 2) {
                            downMove = true;
                            iconParams.x = (int) (event.getRawX() - startX);
                            iconParams.y = (int) (event.getRawY() - startY);
                            updateViewLayout();
                        }
                        return true;
                    case MotionEvent.ACTION_UP:
                        long curTime = System.currentTimeMillis();
                        isMove = curTime - startTime > 100;
                        if (isMove) {
                            if (iconParams.x + iconView.getMeasuredWidth() / 2 >= windowManager.getDefaultDisplay().getWidth() / 2) {
                                finalMoveX = windowManager.getDefaultDisplay().getWidth() - iconView.getMeasuredWidth();
                            } else {
                                finalMoveX = 0;

                            }
                            animator = ValueAnimator.ofInt(iconParams.x, finalMoveX).setDuration(Math.abs(iconParams.x - finalMoveX));
                            animator.addUpdateListener((ValueAnimator animation) -> {
                                if (animation != null) {
                                    moveX = (int) animation.getAnimatedValue();
                                    iconParams.x = (int) animation.getAnimatedValue();
                                    updateViewLayout();
                                }
                            });
                            animator.start();
                        }

                        return isMove;
                }
                return false;
            }
        });
    }

    private void updateViewLayout() {
        if (null != iconView && null != iconParams && windowManager != null) {
            try {
                windowManager.updateViewLayout(iconView, iconParams);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static int dp2px(Context context, float dpValue) {
        return DensityUtils.dipToPx(context, dpValue);
    }

    @Override
    public void sendLog(LogCategory logCategory, LogMessage logMessage) {
        logView.sendLog(logCategory, logMessage);
    }

    @Override
    public void sendLog(LogCategory logCategory, Diagnostic diagnostic) {
        logView.sendLog(logCategory, diagnostic);
    }

    @Override
    public void sendLog(LogCategory logCategory, Throwable throwable) {
        logView.sendLog(logCategory, throwable);
    }

    @Override
    public void setOnHyperLinkClickListener(LogView.OnHyperLinkClickListener onHyperLinkClickListener) {
        logView.setOnHyperLinkClickListener(onHyperLinkClickListener);
    }

    @Override
    public void clear(LogCategory logCategory) {
        logView.clear(logCategory);
    }

    @Override
    public void clearAll() {
        logView.clearAll();
    }
}